package com.chatplus.application.service.wxmp.impl;

import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.chatplus.application.config.properties.WechatMpProperties;
import com.chatplus.application.service.account.impl.WechatUserServiceImpl;
import com.chatplus.application.service.wxmp.WeChatMpEventKeyHandler;
import com.chatplus.application.service.wxmp.handler.MsgHandler;
import com.chatplus.application.service.wxmp.handler.ScanHandler;
import com.chatplus.application.service.wxmp.handler.SubscribeHandler;
import com.chatplus.application.service.wxmp.handler.UnsubscribeHandler;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import jakarta.annotation.PostConstruct;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import static me.chanjar.weixin.common.api.WxConsts.EventType.*;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;

/**
 * 根据事件类型来选择处理器
 *
 * @author chj
 * @date 2024/4/1
 **/
@Service
public class WeChatMpService extends WxMpServiceImpl {

    static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(WeChatMpService.class);

    private final WechatMpProperties wechatMpProperties;
    // 缓存服务
    private static final Cache<String, WeChatMpEventKeyHandler> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(WechatUserServiceImpl.EXPIRE_SECONDS * 1000L, TimeUnit.MILLISECONDS)
            .build();
    private WxMpMessageRouter router;
    protected ScanHandler scanHandler;
    private final MsgHandler msgHandler;
    private final UnsubscribeHandler unsubscribeHandler;
    private final SubscribeHandler subscribeHandler;

    @Autowired
    public WeChatMpService(
            WechatMpProperties wechatMpProperties,
            @Lazy ScanHandler scanHandler,
            @Lazy MsgHandler msgHandler,
            @Lazy UnsubscribeHandler unsubscribeHandler,
            @Lazy SubscribeHandler subscribeHandler) {
        this.scanHandler = scanHandler;
        this.msgHandler = msgHandler;
        this.unsubscribeHandler = unsubscribeHandler;
        this.subscribeHandler = subscribeHandler;
        this.wechatMpProperties = wechatMpProperties;
    }
    @PostConstruct
    public void init() {
        if (wechatMpProperties == null || !wechatMpProperties.isEnable()) {
            return;
        }
        final WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
        // 设置微信公众号的appid
        config.setAppId(wechatMpProperties.getAppId());
        // 设置微信公众号的app corpSecret
        config.setSecret(wechatMpProperties.getSecret());
        // 设置微信公众号的token
        config.setToken(wechatMpProperties.getToken());
        // 设置消息加解密密钥
        config.setAesKey(wechatMpProperties.getAesKey());
        super.removeConfigStorage(wechatMpProperties.getAppId());
        super.setWxMpConfigStorage(config);
        this.refreshRouter();
        LOGGER.message("已配置微信公众号配置").info();
    }

    public void addHandler(String key, WeChatMpEventKeyHandler weChatMpEventKeyHandler) {
        cache.put(key, weChatMpEventKeyHandler);
    }

    /**
     * 通过场景值来获取对应的处理器
     *
     * @param sceneStr 每个二维码都对应一个维一的场景值sceneStr
     *                 该sceneStr是创建ticket时的参数
     * @return 事件处理器
     */
    public WeChatMpEventKeyHandler getHandler(String sceneStr) {
        LOGGER.message("key:" + sceneStr).info();
        return cache.getIfPresent(sceneStr);
    }

    private void refreshRouter() {
        final WxMpMessageRouter newRouter = new WxMpMessageRouter(this);
        // 关注事件
        newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
        // 取消关注事件
        newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
        // 扫码事件
        newRouter.rule().async(false).msgType(EVENT).event(SCAN).handler(this.scanHandler).end();
        // 默认
        newRouter.rule().async(false).handler(this.msgHandler).end();
        this.router = newRouter;
    }

    /**
     * 微信事件通过这个入口进来
     */
    public WxMpXmlOutMessage route(WxMpXmlMessage message) {
        try {
            return this.router.route(message);
        } catch (Exception e) {
            LOGGER.message("微信路由报错").context("message", message).exception(e).error();
        }
        return null;
    }
}
